package com.zwcl.common.core.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;

import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @Description Json工具类
 * @Author Jason
 * @Date 2019/7/23 15:11
 * @Email jason@wetax.com.cn
 */
public final class JsonUtils {

    /**
     * 私有化构造器
     */
    private JsonUtils() {
    }

    /**
     * 定义Jackson的ObjectMapper实例对象
     */
    private static final ObjectMapper MAPPER = new ObjectMapper();

    /**
     * 定义Jackson的ObjectMapper实例对象
     */
    private static final ObjectMapper MAPPER_NON_NULL = new ObjectMapper();

    static {
        // 设置自己的日期转换工具，以便处理 yyyy-MM-dd HH:mm:ss 日期格式
        MAPPER.setDateFormat(new SimpleDateFormat(DateUtils.YYYY_MM_DD_HH_MM_SS));

        MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        //忽略多余字段
        MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        //忽略字段大小写
        //MAPPER.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);

        //该特性决定是否接受强制非数组（JSON）值到Java集合类型。如果允许，集合反序列化将尝试处理非数组值
        MAPPER.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);

    }

    /**
     * 创建对象
     *
     * @return 返回对象
     */
    public static ObjectMapper getObjectMapper() {
        return MAPPER;
    }

    /**
     * 将对象转换成json字符串。
     *
     * @param data 目标数据
     * @return 返回Json字符串
     */
    public static String objectToJson(Object data) {
        try {
            return MAPPER.writeValueAsString(data);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 将json结果集转化为对象
     *
     * @param json     json数据
     * @param beanType 对象中的object类型
     * @param <T>      POJO类型
     * @return 返回目标POJO实例对象
     */
    public static <T> T jsonToPojo(String json, Class<T> beanType) {
        try {
            if (StringUtils.isBlank(json) || null == beanType) {
                return null;
            }
            T t = MAPPER.readValue(json, beanType);
            return t;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 将json数据转换成pojo对象list
     *
     * @param json     Json字符串
     * @param beanType POJO的Class
     * @param <T>      POJO类型
     * @return 返回目标POJO的集合
     */
    public static <T> List<T> jsonToList(String json, Class<T> beanType) {
        try {
            JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);
            return MAPPER.readValue(json, javaType);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 将map转化成pojo对象
     *
     * @param map   源数据
     * @param clazz POJO的Class
     * @param <T>   POJO类型
     * @return 返回目标POJO
     */
    public static <T> T map2obj(Map<?, ?> map, Class<T> clazz) {
        try {
            return JSON.parseObject(JSON.toJSONString(map), clazz);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 将对象转换成json字符串。
     *
     * @param data 目标数据
     * @return 返回Json字符串
     */
    public static String objectToJsonIgnoreNull(Object data) {
        try {
            return MAPPER_NON_NULL.writeValueAsString(data);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 下划线转驼峰
     *
     * @param json 下划线json串
     * @return
     */
    public static String underline2Camel(String json) {
        Object obj = JSON.parse(json);
        convert(obj);
        return objectToJson(obj);
    }

    public final static void convert(Object json) {
        if (json instanceof JSONArray) {
            JSONArray arr = (JSONArray) json;
            for (Object obj : arr) {
                convert(obj);
            }
        } else if (json instanceof JSONObject) {
            JSONObject jo = (JSONObject) json;
            Set<String> keys = jo.keySet();
            String[] array = keys.toArray(new String[keys.size()]);
            for (String key : array) {
                Object value = jo.get(key);
                String[] key_strs = key.split("_");
                if (key_strs.length > 1) {
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < key_strs.length; i++) {
                        String ks = key_strs[i];
                        if (!"".equals(ks)) {
                            if (i == 0) {
                                sb.append(ks);
                            } else {
                                int c = ks.charAt(0);
                                if (c >= 97 && c <= 122) {
                                    int v = c - 32;
                                    sb.append((char) v);
                                    if (ks.length() > 1) {
                                        sb.append(ks.substring(1));
                                    }
                                } else {
                                    sb.append(ks);
                                }
                            }
                        }
                    }
                    jo.remove(key);
                    jo.put(sb.toString(), value);
                }
                convert(value);
            }
        }
    }
}
